﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ScriptCoreLib;
using AvalonTycoonMansion.Shared.Isometric;
using ScriptCoreLib.Shared.Lambda;
using ScriptCoreLib.Shared.Avalon.Extensions;
using System.Windows.Media;

namespace AvalonTycoonMansion.Shared
{
    [Script]
    public class PropertyManager
    {

        [Script]
        public class AvailableProperty : IDisposable
        {
            public event Action AnalyticChanged;
            PropertyValueAnalytic InternalAnalytic;
            public PropertyValueAnalytic Analytic
            {
                get
                {
                    return InternalAnalytic;
                }
                set
                {
                    InternalAnalytic = value;

                    Update();

                    if (AnalyticChanged != null)
                        AnalyticChanged();
                }
            }

            bool InternalValueSpecified;
            int InternalValue;
            public int MinimumValue = 1;

            public int Value
            {
                get { return InternalValue; }
                set
                {
                    InternalValue = Math.Max(value, MinimumValue);
                    InternalValueSpecified = true;

                    Update();
                }
            }

            private void Update()
            {
                if (!InternalValueSpecified)
                    return;

                var q = InternalAnalytic.GetQuote(InternalValue);

                this.SignButton.Text = q.Text;
                this.SignButton.Foreground = q.Color;
            }



            IsometricContainerTile InternalTile;
            public IsometricContainerTile Tile
            {
                get
                {
                    return InternalTile;
                }
                set
                {
                    if (InternalTile != null)
                    {
                        // does this work?
                        InternalTile.BuildingChanged -= GetAltitudeFromBuilding;

                        Fill(InternalTile, null);
                    }

                    InternalTile = value;

                    if (value == null)
                        return;

                    Fill(value, this);

                    GetAltitudeFromBuilding();


                    this.Sign.MoveTo(value.X + 0.5 * value.Description.SizeX, value.Y - 0.5 * value.Description.SizeY);

                    InternalTile.BuildingChanged += GetAltitudeFromBuilding;

                }
            }

            private void GetAltitudeFromBuilding()
            {
                /*
TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at AvalonTycoonMansion.Shared::PropertyManager_AvailableProperty/GetAltitudeFromBuilding_100663472()
    at Function/http://adobe.com/AS3/2006/builtin::apply()
    at ScriptCoreLib.ActionScript.BCLImplementation.System::__Action/Invoke_100665366()
    at AvalonTycoonMansion.Shared.Isometric::IsometricContainer_Tile/set Building()
    at AvalonTycoonMansion.Shared.Isometric::IsometricContainer_Tile/set Description()
    at AvalonTycoonMansion.Shared::PlaygroundBuilder/Animate_100663297()
    at AvalonTycoonMansion.Shared::OrcasAvalonApplicationCanvas___c__DisplayClass25/__ctor_b__1b_100663540()
    at Function/http://adobe.com/AS3/2006/builtin::apply()
    at ScriptCoreLib.ActionScript.BCLImplementation.System::__Action/Invoke_100665366()
    at ScriptCoreLib.Shared.Avalon.Extensions::AvalonSharedExtensions___c__DisplayClass2b/_AtInterval_b__2a_100664802()
    at Function/http://adobe.com/AS3/2006/builtin::apply()
    at ScriptCoreLib.ActionScript.BCLImplementation.System::__EventHandler/Invoke_100663719()
    at ScriptCoreLib.ActionScript.BCLImplementation.System.Windows.Threading::__DispatcherTimer/_Start_b__0_100664295()
    at flash.utils::Timer/_timerDispatch()
    at flash.utils::Timer/tick()
				 
				 
                 */

                if (InternalTile == null)
                    return;

                if (InternalTile.Building == null)
                    return;

                this.Sign.Altitude = InternalTile.Building.Height + InternalTile.Building.Altitude - 7;
            }

            private void Fill(IsometricContainerTile value, AvailableProperty n)
            {
                for (int i = 0; i < value.Description.SizeX; i++)
                {
                    for (int j = 0; j < value.Description.SizeY; j++)
                    {
                        this.PropertyManager[value[i, -j]] = n;
                    }
                }
            }

            public readonly PropertyManager PropertyManager;

            readonly IsometricContainer.Sprite Sign;
            readonly TycoonButton SignButton;

            public readonly AnimatedOpacity SignOpacity;

            public AvailableProperty(PropertyManager PropertyManager)
            {
                this.PropertyManager = PropertyManager;


                this.Sign = new IsometricContainer.Sprite(PropertyManager.Context, 64, 14)
                {
                    IsOverlay = true,
                };

                this.SignButton = new TycoonButton(64, 14)
                {
                    Text = "▲ " + 1234.ToDollarString(),
                    Foreground = 0xff00ff00.ToSolidColorBrush()
                }.AttachContainerTo(this.Sign);

                this.SignOpacity = this.SignButton.BackgroundContainer.ToAnimatedOpacity();
                this.SignOpacity.Opacity = 0;

            }

            public void Dispose()
            {
                this.Sign.OrphanizeContainer();
                this.Tile = null;
            }
        }

        public readonly IsometricContainer Context;

        readonly AvailableProperty[] ByTile;

        public PropertyManager(IsometricContainer Context)
        {
            this.Context = Context;
            this.ByTile = new AvailableProperty[Context.Tiles.Length];
        }

        public AvailableProperty this[IsometricContainerTile t]
        {
            set
            {
                this.ByTile[t.Y + t.X * this.Context.SizeY] = value;
            }
            get
            {
                return this.ByTile[t.Y + t.X * this.Context.SizeY];
            }
        }

        AvailableProperty InternalSelection;
        public AvailableProperty Selection
        {
            get
            {
                return InternalSelection;
            }
            set
            {
                if (InternalSelection == value)
                    return;

                if (InternalSelection != null)
                    InternalSelection.SignOpacity.Opacity = 0;

                InternalSelection = value;

                if (InternalSelection != null)
                    InternalSelection.SignOpacity.Opacity = 1;
            }
        }
    }
}
